
#ifndef DAN_COLOR_BLEND
#define DAN_COLOR_BLEND


//------------from IQ--------------
float4 LerpColor (float t, float4 a, float4 b){ return lerp(a,b,saturate(t));}

float4 BlendColor(float t,float4 a, float4 b,float4 c , float midVal){
	float4 col1 =lerp (a,b,t/midVal);
	float4 col2 =lerp(b,c,(t-midVal)/(1-midVal));
	return lerp(col1,col2,step(midVal,t));
}

float3 CosBlendColor(float t,float3 a, float3 b,float3 c , float3 d){ return a+b*cos(6.283185*(c*(t)+d)); }
           


//----------from ps--------------------

//--------色相----------

//去色
float3 Saturation (float3 base, float satruration)
{ float grey = dot(base, float3(0.2126729, 0.7151522, 0.0721750)); return  base =  grey + satruration * (base - grey);}
//替换
float3 ReplaceColor(float3 inCol, float3 fromCol, float3 toCol, float range, float fuzz ){
	float dis =distance(fromCol, inCol);
	float3 outCol =lerp(toCol, inCol, saturate((dis - range) / max(fuzz, 1e-5)));
	return outCol;
}

//--------加深----------
//变暗          
float4 BlendColorDarken(float4 base, float4 blend, float opacity)
{float4 outCol=min(blend,base);return outCol=lerp(base,outCol,opacity);}

//正片叠底
float4 BlendColorMultiply(float4 base, float4 blend, float opacity)
{float4 outCol = base*blend;return outCol=lerp(base,outCol,opacity);}

//颜色加深
float4 BlendColorBurn(float4 base, float4 blend, float opacity)
{float4 outCol=1-(1-blend)/base;return outCol=lerp(base,outCol,opacity);}

//线性加深
float4 BlendColorLinearBurn(float4 base, float4 blend, float opacity)
{float4 outCol = base+blend-1;return outCol=lerp(base,outCol,opacity);}

//--------减淡----------
//变亮
float4 BlendColorLighten(float4 base, float4 blend, float opacity)
{float4 outCol = max(blend,base);return outCol=lerp(base,outCol,opacity);}

//滤色
float4 BlendColorScreen(float4 base, float4 blend, float opacity)
{float4 outCol = 1.0 - (1.0 - blend) * (1.0 - base);return outCol=lerp(base,outCol,opacity);}

//颜色减淡
float4 BlendColorDogde(float4 base, float4 blend, float opacity)
{float4 outCol=base/(1-blend);return outCol=lerp(base,outCol,opacity);}

//线性减淡（添加）
float4 BlendColorLinearDodge(float4 base, float4 blend, float opacity)
{float4 outCol = base+blend; return outCol=lerp(base,outCol,opacity);}

//--------对比----------
//叠加
float4 BlendColorOverlay(float4 base, float4 blend, float opacity)
{
   float4 result1 = 1.0 - 2.0 * (1.0 - base) * (1.0 - blend);
   float4 result2 = 2.0 * base * blend;
   float4 zeroOrOne = step(base, 0.5);
   float4 outCol = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
   return outCol=lerp(base,outCol,opacity);
}

//柔光
float4 BlendColorSoftLight(float4 base, float4 blend, float opacity)
{
	float4 result1 = 2.0 * base * blend + base * base * (1.0 - 2.0 * blend);
	float4 result2 = sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend);
	float4 zeroOrOne = step(0.5, blend);
	float4 outCol =result2 * zeroOrOne + (1 - zeroOrOne) * result1;
	return outCol=lerp(base,outCol,opacity);
}

//强光
float4 BlendColorHardLight(float4 base, float4 blend, float opacity)
{
	float4 result1 = 1.0 - 2.0 * (1.0 - base) * (1.0 - blend);
	float4 result2 = 2.0 * base * blend;
	float4 zeroOrOne = step(blend, 0.5);
	float4 outCol = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
	return outCol=lerp(base,outCol,opacity);
}

//亮光
float4 BlendColorVividLight(float4 base, float4 blend, float opacity)
{
	float4 result1 = 1.0 - (1.0 - blend) / (2.0 * base);
	float4 result2 = blend / (2.0 * (1.0 - base));
	float4 zeroOrOne = step(0.5, base);
	float4 outCol =result2 * zeroOrOne + (1 - zeroOrOne) * result1;
	return outCol=lerp(base,outCol,opacity);
}

//线性光
float4 BlendColorLinearLight(float4 base, float4 blend, float opacity){
	float4 outCol = blend < 0.5 ? max(base + (2 * blend) - 1, 0) : min(base + 2 * (blend - 0.5), 1);
	return outCol=lerp(base,outCol,opacity);
}

//线性光(加减)
float4 BlendColorLinearLightAddSub(float4 base, float4 blend, float opacity)
{float4 outCol = blend+2*base-1;return outCol=lerp(base,outCol,opacity);}

//点光
float4 BlendColorPinLight(float4 base, float4 blend, float opacity)
{
	float4 check = step (0.5, blend);
	float4 result1 = check * max(2.0 * (base - 0.5), blend);
	float4 outCol = result1 + (1.0 - check) * min(2.0 * base, blend);
	return outCol=lerp(base,outCol,opacity);
}

//实色混合
float4 BlendColorHardMix(float4 base, float4 blend, float opacity)
{float4 outCol = step(1 - base, blend);return outCol=lerp(base,outCol,opacity);}

//--------差集----------
//差值
float4 BlendColorDifference(float4 base, float4 blend, float opacity)
{ float4 outCol=abs(blend-base);return outCol=lerp(base,outCol,opacity);}


//排除
float4 BlendColorExclusion(float4 base, float4 blend, float opacity)
{ float4 outCol=blend + base - (2.0 * blend * base); return outCol=lerp(base,outCol,opacity); }


//划分
float4 BlendColorDivide(float4 base, float4 blend, float opacity)
{float4 outCol=base/(blend+0.000000001);return outCol=lerp(base,outCol,opacity);}



//减去
float4 BlendColorSubtract(float4 base, float4 blend, float opacity)
{  float4 outCol =base-blend;return outCol=lerp(base,outCol,opacity);}



//反色
float4 BlendColorNegation(float4 base, float4 blend, float opacity)
{float4 outCol = 1.0 - abs(1.0 - blend - base);return outCol=lerp(base,outCol,opacity);}



// ------------from shader weaver----------------
float BlendAddf(float base,float act){	return min(base+act, 1.0);}
float BlendSubstractf(float base,float act){return max(base + act - 1.0, 0.0);}
float BlendLightenf(float base,float act){return max(base, act);}
float BlendDarkenf(float base,float act){return min(base,act);}
float BlendLinearLightf(float base,float act){return (act < 0.5 ? BlendSubstractf(base, (2.0 * act)) : BlendAddf(base, (2.0 * (act - 0.5))));}
float BlendScreenf(float base,float act){return (1.0 - ((1.0 - base) * (1.0 - act)));}
float BlendOverlayf(float base,float act){return (base < 0.5 ? (2.0 * base * act) : (1.0 - 2.0 * (1.0 - base) * (1.0 - act)));}
float BlendSoftLightf(float base,float act){return ((act < 0.5) ? (2.0 * base * act + base * base * (1.0 - 2.0 * act)) : (sqrt(base) * (2.0 * act - 1.0) + 2.0 * base * (1.0 - act)));}
float BlendColorDodgef(float base,float act){return 	((act == 1.0) ? base : min(base / (1.0 - act), 1.0));}
float BlendColorBurnf(float base,float act){return ((act == 0.0) ? base : max((1.0 - ((1.0 - base) / act)), 0.0));}
float BlendVividLightf(float base,float act){return ((act < 0.5) ? BlendColorBurnf(base, (2.0 * act)) : BlendColorDodgef(base, (2.0 * (act - 0.5))));}
float BlendPinLightf(float base,float act){return ((act < 0.5) ? BlendDarkenf(base, (2.0 * act)) : BlendLightenf(base, (2.0 *(act - 0.5))));}
float BlendHardMixf(float base,float act){return ((BlendVividLightf(base, act) < 0.5) ? 0.0 : 1.0);}
float BlendReflectf(float base,float act){return ((act == 1.0) ? act : min(base * base / (1.0 - act), 1.0));}
float BlendDarkerColorf(float base,float act){return clamp(base-(1-base)*(1-act)/act,0,1);}

float3 BlendDarken(float3 base,float3 act){return min(base,act);}
float3 BlendColorBurn(float3 base, float3 act) {return float3(BlendColorBurnf(base.r,act.r),BlendColorBurnf(base.g,act.g),BlendColorBurnf(base.b,act.b));}
float3 BlendLinearBurn(float3 base,float3 act){return max(base + act - 1,0);}
float3 BlendDarkerColor(float3 base,float3 act){return (base.r+base.g+base.b)>(act.r+act.g+act.b)?act:base;}
float3 BlendLighten(float3 base,float3 act){return max(base, act);}
float3 BlendScreen(float3 base,float3 act){return float3(BlendScreenf(base.r,act.r),BlendScreenf(base.g,act.g),BlendScreenf(base.b,act.b));}
float3 BlendColorDodge(float3 base,float3 act){return float3(BlendColorDodgef(base.r,act.r),BlendColorDodgef(base.g,act.g),BlendColorDodgef(base.b,act.b));}
float3 BlendLinearDodge(float3 base,float3 act){return min(base+act, 1.0);}
float3 BlendLighterColor(float3 base,float3 act){return (base.r+base.g+base.b)>(act.r+act.g+act.b)?base:act;}
float3 BlendOverlay(float3 base,float3 act){return  float3(BlendOverlayf(base.r,act.r),BlendOverlayf(base.g,act.g),BlendOverlayf(base.b,act.b));}
float3 BlendSoftLight(float3 base,float3 act){return float3(BlendSoftLightf(base.r,act.r),BlendSoftLightf(base.g,act.g),BlendSoftLightf(base.b,act.b));}
float3 BlendHardLight(float3 base,float3 act){return BlendOverlay(act, base);}
float3 BlendVividLight(float3 base,float3 act){return float3(BlendVividLightf(base.r,act.r),BlendVividLightf(base.g,act.g),BlendVividLightf(base.b,act.b));}
float3 BlendLinearLight(float3 base,float3 act){return float3(BlendLinearLightf(base.r,act.r),BlendLinearLightf(base.g,act.g),BlendLinearLightf(base.b,act.b));}
float3 BlendPinLight(float3 base,float3 act){return float3(BlendPinLightf(base.r,act.r),BlendPinLightf(base.g,act.g),BlendPinLightf(base.b,act.b));}
float3 BlendHardMix(float3 base,float3 act){return float3(BlendHardMixf(base.r,act.r),BlendHardMixf(base.g,act.g),BlendHardMixf(base.b,act.b));}
float3 BlendDifference(float3 base,float3 act){return abs(base - act);}
float3 BlendExclusion(float3 base,float3 act){return (base + act - 2.0 * base * act);}
float3 BlendSubtract(float3 base,float3 act){return max(base - act, 0.0);}



#endif